我們今天兜了三個小工具,
程式在這裡的days/day1python get_transcription.py
是從自帶字幕的youtube連結獲取字幕,存成txt檔python yt_download.py
如果本身沒有自帶字幕的話,就先把影片的音訊檔載下來python whisper_audio2txt.py
然後用whisper轉成文字檔
結果在專案目錄下的data下的lee.txt和hung.json
我們想要替RAG系統獲得成對的(context, question, answer)供後續方法論的驗證
當前的子任務是:先想辦法獲得context,我們後續再prompt llm從context生成(Q, A) pair
這部分的想法是從youtube影片獲取,那這又區分成兩個case:
case1: 當youtube影片有提供字幕的時候,我們直接把字幕載下來
case2: 當youtube影片本身沒有提供字幕的時候,我們可以把音訊檔下載下來,丟給whisper
我們準備了兩個youtube的連結:
一個有字幕的例子:
【生成式人工智慧與機器學習導論2025】第0講:開場與課程簡介
感覺累積起來可以變成發問有關生程式AI的問題->查找李老師的youtube課程並且精確到秒
一個沒有字幕的例子:
# 寶寶睡不過夜?總是半夜起床哭鬧討奶喝怎麼安撫?影響寶寶睡眠的因素是什麼?|黃瑽寧醫師健康講堂【寶寶系列 EP21】
這個可能可以變成一個育兒上有疑難雜症就問他的應用
pip install youtube-transcript-api
sudo apt install -y ffmpeg
pip install yt-dlp
pip install faster-whisper
def _extract_video_id(url: str) -> str:
p = urlparse(url)
if p.netloc.endswith("youtu.be"):
return p.path.lstrip("/").split("/")[0]
q = parse_qs(p.query)
if "v" in q:
return q["v"][0]
m = re.search(r"/(shorts|embed)/([A-Za-z0-9_-]{6,})", p.path)
if m:
return m.group(2)
raise ValueError("無法從網址解析出 YouTube 影片 ID。")
def has_youtube_captions(url: str, preferred_langs=None) -> bool:
from youtube_transcript_api import YouTubeTranscriptApi
from youtube_transcript_api._errors import TranscriptsDisabled
from youtube_transcript_api import NoTranscriptFound
video_id = _extract_video_id(url)
api = YouTubeTranscriptApi()
try:
tlist = api.list(video_id) # TranscriptList,可疊代
except (TranscriptsDisabled, NoTranscriptFound):
return False
except Exception:
return False
if preferred_langs:
try:
tlist.find_transcript(preferred_langs)
return True
except NoTranscriptFound:
return False
else:
return len(list(tlist)) > 0
def fetch_youtube_captions(
url: str,
preferred_langs=None,
translate_to: str | None = None,
join_with: str = "\n",
preserve_formatting: bool = False,
) -> str:
if preferred_langs is None:
preferred_langs = ["zh-Hant", "zh-TW", "zh-Hans", "zh", "en"]
video_id = _extract_video_id(url)
from youtube_transcript_api import YouTubeTranscriptApi, NoTranscriptFound
api = YouTubeTranscriptApi()
if translate_to:
# 先找到一個字幕,再翻譯
tlist = api.list(video_id)
try:
base_t = tlist.find_transcript(preferred_langs)
except NoTranscriptFound:
base_t = next(iter(tlist), None)
fetched = base_t.translate(translate_to).fetch(preserve_formatting=preserve_formatting)
else:
fetched = api.fetch(video_id, languages=preferred_langs, preserve_formatting=preserve_formatting)
raw = fetched.to_raw_data()
lines = [d["text"].strip() for d in raw if d.get("text", "").strip()]
junk = {"[Music]", "[Applause]", "[Laughter]"}
return join_with.join([ln for ln in lines if ln not in junk])
到這邊看一下結果:
text = fetch_youtube_captions(links[0])
print(text[:30])
'各位同學大家好 我們來上課吧\n剛才只是用Google的VO3'
我們要先用yt_dlp把影片載下來,這個如果安裝上有問題,我覺得就直接去colab上用比較省事
4. 下載mp3
def download_audio(url, output):
ydl_opts = {
"format": "bestaudio/best",
"outtmpl": output,
"postprocessors": [{
"key": "FFmpegExtractAudio",
"preferredcodec": "mp3",
"preferredquality": "192"
}]
}
with yt_dlp.YoutubeDL(ydl_opts) as ydl:
ydl.download([url])
return output
output_path = 'audio.mp3'
download_audio(links[1], output_path)
到這邊路徑下會有一個audio.mp3檔案,點開來就是影片的語音檔了。
5. 用faster_whisper 把mp3轉txt
from faster_whisper import WhisperModel
from pathlib import Path
def transcribe_faster_whisper(
audio_file: str | Path,
model_name: str = "large-v3",
device: str = "auto", # "cuda" | "cpu" | "auto"
compute_type: str = "auto", # "float16" | "int8_float16" | "int8" | "auto"
language: str | None = None, # "zh"、"en"、None=自動偵測
):
audio_file = str(audio_file)
model = WhisperModel(model_name, device=device, compute_type=compute_type)
segments, info = model.transcribe(
audio_file,
language=language,
vad_filter=True, # 內建 Voice Activity Detection,通常品質更穩
beam_size=5,
)
# 收集所有 segments
segs = []
full_text = []
for seg in segments:
segs.append({"start": seg.start, "end": seg.end, "text": seg.text})
full_text.append(seg.text)
return {
"text": " ".join(full_text).strip(),
"segments": segs,
"language": info.language,
"language_probability": info.language_probability,
}
到這邊看一下結果:
zh 0.9990234375
大家平安 我是黃宗霖醫師 在當新手父母的過程當中 寶寶的睡眠這件事情 一直都是我們黃宗霖醫師健康講上 留人區最頻繁被爸媽提出來的問題 而且我自己孩子很小的時候 我曾經腦袋有一種邪惡的一種念頭 就是當寶
dur: 46.231650829315186 sec
可以看到比如人名的辨識會有問題,沒有標點,還有一些特殊的詞彙也做不好,但也就堪用吧!
如果faster_whisper執行有問題的話,通常是因為找不到cudnn
我遇到的是顯示:
Unable to load any of {libcudnn_ops.so.9.1.0, libcudnn_ops.so.9.1, libcudnn_ops.so.9, libcudnn_ops.so}
Invalid handle. Cannot load symbol cudnnCreateTensorDescriptor
Aborted (core dumped)
除了直接安裝cudnn以外:pip install -U --no-cache-dir nvidia-cudnn-cu12 ctranslate2
還要記得把lib加到LD_LIBRARY_PATH
export LD_LIBRARY_PATH="$(
python - <<'PY'
import os, site
libdirs=[]
for base in site.getsitepackages()+[site.getusersitepackages()]:
for sub in [("nvidia","cudnn","lib"), ("nvidia","cublas","lib")]:
d=os.path.join(base, *sub)
if os.path.isdir(d): libdirs.append(d)
print(":".join(libdirs))
PY
):${LD_LIBRARY_PATH}"
再不然就是改用cpu跑model選tiny其實也不慢
老樣子,本地環境弄不起來的話就可以直接去colab上用省事
我們今天兜了兩個小工具,
一個是從自帶字幕的youtube連結獲取字幕,準備當成上下文
一個是當youtube影片本身沒有附字幕的時候,我們把它下載下來,再用whisper轉成文字檔